/*
 * @Date: 2025-02-14 16:01:58
 * @Author: LiSong
 * @LastEditors: LiSong
 * @LastEditTime: 2025-02-14 16:02:01
 * @Description: 执行方法字符串的工具类
 */

import { ElMessage } from 'element-plus'
import { pluginManager } from '@hp/utils/pluginManager.js'

// 执行方法的this
const funcThis = { ElMessage, pluginManager, getPanelRef: (id) => pluginManager.getPanelRef(id) }
// 方法前缀
const funcPrefix = 'func:'

/**
 * js中执行方法体字符串的方法
 * 
 * funcConfig {
 *  resType: 返回参数类型,
 *  paramNames: 参数名定义,
 *  paramObjects: 参数名对应对象的值
 *  errorTip: 错误信息提示
 * }
 * 
 * @param {String} funcText 
 * @param {Object} funcConfig { resType, paramNames, paramObjects, errorTip }
 * @returns 
 */
export const executeFuncText = (funcText, funcConfig) => {
  funcText = funcText.replace(funcPrefix, '')
  if (!funcText) {
    console.warn('方法体不能为空');
    return
  }
  const { resType, paramNames, paramObjects, errorTip, defaultValue } = funcConfig
  let defRes = resType ? resType === 'string' ? '' : defaultValue || {} : ''
  let result = defRes
  try {
    const executeFunc = new Function(...paramNames, funcText)
    const executeThis = { ...funcThis, ...paramObjects }
    const paramObjectArray = paramNames.map(key => paramObjects[key])
    result = executeFunc.call(executeThis, ...paramObjectArray) || defRes
  } catch (error) {
    throw createCustomException(error, errorTip || '函数解析出错')
  }
  return result
}

/**
 * 重新抛出一个 Error 对象，以便于在 catch 时能够正确的拿到自定义的错误信息
 * 
 * @param {Error} error 原始的错误对象
 * @param {String} desc 自定义的错误描述
 * @returns {Error} 重新抛出的错误对象
 */
export const createCustomException = (error, desc) => {
  const e = new Error(`${desc}: ${error.message}`);
  e.stack = error.stack;
  e.originalError = error;
  return e
}
